/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 * Description: notify基类
 */

#ifndef NOTIFY_BASE_H
#define NOTIFY_BASE_H

#include "adapter_rts.h"
#include "adapter_hal.h"
#include "base.h"

#include "stream.h"
#include "mem_name_repository_pub.h"
#include "dispatcher_pub.h"

namespace hccl {

enum class NotifyType {
    RUNTIME_NOTIFY = 0,
    RUNTIME_NOTIFY_MC2,
    BARE_NOTIFY,
    ESCHED_EVENT,
    NOTIFY_TYPE_RESERVED
};

constexpr s32 IPC_NOTIFY_PID_ARRAY_SIZE = 1;

using HcclIpcRtsNotify = struct TagHcclIpcRtsNotify {
    u8 ipcName[HCCL_IPC_MEM_NAME_LEN] = {0};
    bool withIpc;
    HcclRtNotify ptr;
    u32 id;
    u64 offset;

    TagHcclIpcRtsNotify() : withIpc(false), ptr(nullptr), id(INVALID_UINT), offset(INVALID_U64)
    {
    }
};

using HcclNotifyInfo = struct TagHcclNotifyInfo {
    u32 type;
    HcclIpcRtsNotify ipcNotify;
    rtIpcIntNoticeInfo_t eschedEvent;

    TagHcclNotifyInfo() : type(INVALID_UINT)
    {
    }

    TagHcclNotifyInfo(const TagHcclNotifyInfo& that) : type(that.type), ipcNotify(that.ipcNotify),
        eschedEvent(that.eschedEvent)
    {
    }

    TagHcclNotifyInfo(const TagHcclNotifyInfo&& that) : type(that.type), ipcNotify(that.ipcNotify),
        eschedEvent(that.eschedEvent)
    {
    }

    TagHcclNotifyInfo &operator=(const TagHcclNotifyInfo &that)
    {
        if (&that != this) {
            type = that.type;
            ipcNotify = that.ipcNotify;
            eschedEvent = that.eschedEvent;
        }
        return *this;
    }
};

class NotifyBase {
public:
    NotifyBase(NotifyType notifyType) : notifyType(notifyType)
    {
        notifyInfo_.type = static_cast<u32>(notifyType);
    }

    NotifyBase(NotifyType notifyType, HcclNotifyInfo notifyInfo) : notifyType(notifyType), notifyInfo_(notifyInfo)
    {
    }

    NotifyBase(NotifyType notifyType, HcclSignalInfo notifyInfo) : notifyType(notifyType)
    {
        HCCL_ERROR("[NotifyConstructor]Does not support this interface.");
    }

    virtual ~NotifyBase()
    {
    }

    HcclResult Serialize(std::vector<u8> &byteVector)
    {
        std::vector<u8> data = CustomTypeToVectorByte<HcclNotifyInfo>(notifyInfo_);
        if (data.empty() || data.size() > NOTIFY_INFO_LENGTH) {
            HCCL_ERROR("serialize msgSize[%u] > NOTIFY_INFO_LENGTH[%u]", data.size(), NOTIFY_INFO_LENGTH);
            return HCCL_E_INTERNAL;
        }

        std::vector<u8> paddingData(NOTIFY_INFO_LENGTH - data.size(), 0);
        HCCL_DEBUG("[Serialize]data size[%u], paddingData[%u].", data.size(), paddingData.size());
        data.insert(data.end(), paddingData.begin(), paddingData.end());

        byteVector = data;

        return HCCL_SUCCESS;
    }

    static HcclResult Deserialize(const std::vector<u8>& byteVector, HcclNotifyInfo &notifyInfo)
    {
        CHK_SAFETY_FUNC_RET(memcpy_s((u8 *)&notifyInfo, sizeof(HcclNotifyInfo),
            &byteVector[0], sizeof(HcclNotifyInfo)));
        return HCCL_SUCCESS;
    }

    virtual HcclResult Alloc() = 0;
    virtual HcclResult Destroy() = 0;

    virtual HcclResult Open() = 0;
    virtual HcclResult Close() = 0;

    virtual HcclResult Wait(Stream& stream, HcclDispatcher dispatcher, s32 stage, u32 timeOut) = 0;
    virtual HcclResult Post(Stream& stream, HcclDispatcher dispatcher, s32 stage) = 0;

    virtual HcclResult Wait(Stream& stream, HcclDispatcher dispatcher, s32 stage, u32 timeOut,
        u32 userRank, u32 remoteUserRank) = 0;
    virtual HcclResult Post(Stream& stream, HcclDispatcher dispatcher, s32 stage,
        u32 remoteUserRank) = 0;

    virtual HcclResult SetIpc() = 0;
    virtual HcclResult Grant(s64 recvId) = 0;
    virtual void Break()
    {
        HCCL_ERROR("[Break]Does not support this interface.");
        return;
    }

    virtual HcclResult GetNotifyData(HcclSignalInfo &notifyInfo)
    {
        HCCL_ERROR("[GetNotifyData]Does not support this interface.");
        return HCCL_E_NOT_SUPPORT;
    }

    virtual HcclResult SetNotifyData(const HcclSignalInfo &notifyInfo)
    {
        HCCL_ERROR("[SetNotifyData]Does not support this interface.");
        return HCCL_E_NOT_SUPPORT;
    }

    virtual HcclResult GetNotifyOffset(u64 &offset)
    {
        HCCL_ERROR("[GetNotifyOffset]Does not support this interface.");
        return HCCL_E_NOT_SUPPORT;
    }

    inline HcclRtNotify ptr()
    {
        return notifyPtr;
    }

protected:
    NotifyType notifyType;
    HcclNotifyInfo notifyInfo_;
    HcclRtNotify notifyPtr{nullptr};
};
}

#endif // NOTIFY_BASE_H
